package com.scs.application.modules.cert.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.DictConsts;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.core.global.GlobalDictService;
import com.scs.application.core.utils.BeanUtils;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.service.*;
import com.scs.application.modules.cert.dto.CertRequirementUpdateDO;
import com.scs.application.modules.cert.dto.CertificateUpdateDO;
import com.scs.application.modules.cert.entity.CertificateHospitalBusiness;
import com.scs.application.modules.cert.entity.CertificateRepository;
import com.scs.application.modules.cert.mapper.CertificateRepositoryMapper;
import com.scs.application.modules.cert.request.CertificateHospitalBusinessQueryRequest;
import com.scs.application.modules.cert.request.ChbQueryRequest;
import com.scs.application.modules.cert.request.CrQueryRequest;
import com.scs.application.modules.cert.service.CertificateHospitalBusinessService;
import com.scs.application.modules.cert.vo.ChbVO;
import com.scs.application.modules.cert.service.CertMessageService;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 资质消息
 */
@Slf4j
@AllArgsConstructor
@Service
public class CertMessageServiceImpl implements CertMessageService {

    private final CertificateRequirementService certificateRequirementService;

    private final CertificateHospitalBusinessService certificateHospitalBusinessService;

    private final GlobalDictService globalDictService;

    private final HospitalSupplierService hospitalSupplierService;

    private final CertificateSummaryService certificateSummaryService;

    private final HospitalService hospitalService;

    private final SupplierService supplierService;

    private final MaterialService materialService;

    private final MaterialCatalogService materialCatalogService;

    private final ManufacturerService manufacturerService;

    private final CertificateRepositoryMapper certificateRepositoryMapper;

    @Async
    @Override
    public void certRequirementUpdate(CertRequirementUpdateDO cru) {
        String hospitalId = cru.getHospitalId();
        if (StringUtils.isBlank(hospitalId)) {
            return;
        }
        // 查询出医院所有的资质信息
        ChbQueryRequest chbQueryRequest = new ChbQueryRequest();
        chbQueryRequest.setHospitalId(hospitalId);

        CertificateHospitalBusinessQueryRequest chbRquest = new CertificateHospitalBusinessQueryRequest();
        chbRquest.setHospitalId(chbQueryRequest.getHospitalId()).setCertificateId(chbQueryRequest.getCertificateId());
        List<CertificateHospitalBusiness> list = certificateHospitalBusinessService.list(chbRquest);

        List<ChbVO> result = BeanUtils.copyProperties(list, ChbVO.class);


        log.info("检测到医院[{}]要求上传资质更新，正在更新医院要求上传资质信息..................", hospitalId);

        // 删除已有的资质信息
        certificateRequirementService.remove(
                Wrappers.<CertificateRequirement>query().eq("hospital_id", hospitalId)
        );



        // 依据业务类型进行合并
        Map<String, List<ChbVO>> map = result.stream().collect(Collectors.groupingBy(o -> o.getBusinessTypeCode()));

        List<CertificateRequirement> crList = Lists.newArrayListWithExpectedSize(map.size());
        for (String businessType : map.keySet()) {
            CertificateRequirement cr = new CertificateRequirement();
            cr.setBusinessTypeCode(businessType)
                    .setHospitalId(hospitalId)
                    .setRequiredCnt(Long.valueOf(map.get(businessType).size()));
            crList.add(cr);
        }

        if (!crList.isEmpty()) {
            certificateRequirementService.saveBatch(crList);
        }

        log.info("检测到医院[{}]要求上传资质更新，更新医院要求上传资质信息完毕，总共更新{}条记录..................", hospitalId, crList.size());

    }


    @Async
    @Override
    public void certUploadedUpdate(CertificateUpdateDO cu) {
        String typeCode = cu.getBusinessTypeCode();
        String typeName = globalDictService.getDictLabel("cert_business_type", typeCode, "");
        log.info("检测到{}({})更新，正在更新医院资质汇总信息..................", typeName, typeCode);

        // 获取供应商所有的医院关系
        List<HospitalSupplier> vos = hospitalSupplierService.list(
                Wrappers.<HospitalSupplier>query().eq("supplier_id", cu.getSupplierId())
        );
        if (vos == null || vos.isEmpty()) {
            return;
        }

        int successCnt = 0;
        int hospitalCnt = 0;

        for (HospitalSupplier vo : vos) {
            String hospitalId = vo.getHospitalId();

            // 获取医院要求上传的资质信息
            CertificateHospitalBusinessQueryRequest chbRquest = new CertificateHospitalBusinessQueryRequest();
            chbRquest.setHospitalId(hospitalId).setCertificateId(null);
            List<CertificateHospitalBusiness> list = certificateHospitalBusinessService.list(chbRquest);

            List<ChbVO> chbVOList = BeanUtils.copyProperties(list, ChbVO.class);

            // 检查当前上传的资质是否存在于要求上传的资质中
            /*long count = chbVOList.stream().filter(o -> certificateId.equalsIgnoreCase(o.getCertificateId())).count();
            if (count == 0) {
                log.debug("医院当前上传的资质类型不包含此类资质，医院ID：{}，资质类型：{}({})，资质ID：{}，目标ID：{}",
                        hospitalId, typeName, typeCode, certificateId, cu.getTargetDescribeId());
                continue;
            }*/

            long requiredCnt = chbVOList.stream().filter(
                    o -> typeCode.equalsIgnoreCase(o.getBusinessTypeCode())
            ).count();
            if (requiredCnt == 0) {
                continue;
            }

            // 检查资质汇总中是否存在，如果已存在，直接更新数量
            CertificateSummary cs = certificateSummaryService.getOne(
                    Wrappers.<CertificateSummary>query()
                            .eq("business_type_code", typeCode)
                            .eq("target_describe_id", cu.getTargetDescribeId())
                            .eq("hospital_id", hospitalId)
                            .eq("supplier_id", vo.getSupplierId())
                            .last("limit 1")
            );

            boolean success = false;
            if (cs == null && !cu.isDelete()) {
                // 创建记录
                success = createSummary(hospitalId, (int) requiredCnt, cu);
            } else {
                int uploadedCnt = getUploadedCnt(cu, hospitalId);
                // 更新记录
                success = certificateSummaryService.update(
                        Wrappers.<CertificateSummary>update().eq("id", cs.getId())
                                .set("uploaded_cnt  ", uploadedCnt)
                                .set("required_cnt ", requiredCnt)
                );
            }

            if (success) {
                successCnt++;
                hospitalCnt++;
            }
        }

        log.info("检测到{}({})更新，更新医院资质汇总信息完成，总共更新{}条记录，包含{}家医院..................", typeName, typeCode, successCnt, hospitalCnt);
    }

    /**
     * 创建资质汇总记录
     *
     * @param hospitalId  医院ID
     * @param requiredCnt 要求上传的数量
     * @param cu
     * @return
     */
    public boolean createSummary(String hospitalId, int requiredCnt, CertificateUpdateDO cu) {

        CertificateSummary cs = new CertificateSummary();
        cs.setBusinessTypeCode(cu.getBusinessTypeCode())
                .setTargetDescribeId(cu.getTargetDescribeId());

        Hospital hospital = hospitalService.getById(hospitalId);
        Supplier supplier = supplierService.getById(cu.getSupplierId());


        String catalogId = null;
        String manufacturerId = null;
        if (DictConsts.CERT_BUSINESS_TYPE_MATERIAL.equalsIgnoreCase(cu.getBusinessTypeCode())) {
            Material material = materialService.getById(cu.getTargetDescribeId());
            if (material != null) {
                cs.setMaterialId(material.getId()).setMaterialName(material.getMaterialName());
                manufacturerId = material.getManufacturerId();
                catalogId = material.getCatalogId();
            }
            MaterialCatalog catalog = materialCatalogService.getById(material.getCatalogId());
            if (catalog != null && catalog.getLevel() != 0) {
                // 获取一级品类ID
                int level = catalog.getLevel();
                catalogId = level == 1 ? catalog.getId() : StringUtils.split(catalog.getParentIds(), ",")[1];
            }
        }

        if (DictConsts.CERT_BUSINESS_TYPE_CATALOG1.equalsIgnoreCase(cu.getBusinessTypeCode())) {
            catalogId = cu.getTargetDescribeId();
        }

        if (DictConsts.CERT_BUSINESS_TYPE_MANUFACTURER.equalsIgnoreCase(cu.getBusinessTypeCode())) {
            manufacturerId = cu.getTargetDescribeId();
        }

        if (StringUtils.isNotBlank(manufacturerId)) {
            Manufacturer manufacturer = manufacturerService.getById(manufacturerId);
            if (manufacturer != null) {
                cs.setManufacturerId(manufacturer.getId()).setManufacturerName(manufacturer.getName());
            }
        }
        if (StringUtils.isNotBlank(catalogId)) {
            MaterialCatalog catalog = materialCatalogService.getById(catalogId);
            if (catalog != null) {
                cs.setCatalogId(catalog.getId()).setCatalogCode(catalog.getCode()).setCatalogName(catalog.getName());
            }
        }

        cs.setHospitalId(hospitalId).setHospitalName(hospital.getName());
        cs.setSupplierId(supplier.getId()).setSupplierName(supplier.getName());

        int uploadedCnt = getUploadedCnt(cu, hospitalId);
        cs.setRequiredCnt(requiredCnt).setUploadedCnt(uploadedCnt);

        certificateSummaryService.save(cs);

        return true;
    }

    /**
     * 获取已上传资质数量
     *
     * @param cu
     * @return
     */
    private int getUploadedCnt(CertificateUpdateDO cu, String hospitalId) {
        CrQueryRequest request = new CrQueryRequest();
        request.setBusinessTypeCode(cu.getBusinessTypeCode())
                .setSupplierId(cu.getSupplierId()).setTargetDescribeId(cu.getTargetDescribeId())
                .setSubmitFlag(GlobalConsts.YES_STR).setCloseFlag(GlobalConsts.NO_STR)
                .setHospitalId(hospitalId)
        ;

        // 查询当前医院下所有的资质定义
        CertificateHospitalBusinessQueryRequest queryRequest = new CertificateHospitalBusinessQueryRequest();
        queryRequest.setHospitalId(hospitalId).setBusinessTypeCode(cu.getBusinessTypeCode());
        List<CertificateHospitalBusiness> businessList = certificateHospitalBusinessService.list(queryRequest);
        if (businessList.isEmpty()) {
            return 0;
        }

        // 要求上传的资质中 已上传的数量
        int count = certificateRepositoryMapper.selectCount(
                Wrappers.<CertificateRepository>query()
                        .eq(StringUtils.isNotBlank(request.getCloseFlag()), "close_flag", request.getCloseFlag())
                        .eq(StringUtils.isNotBlank(request.getSubmitFlag()), "submit_flag", request.getSubmitFlag())
                        .eq(StringUtils.isNotBlank(request.getTargetDescribeId()), "target_describe_id", request.getTargetDescribeId())
                        .eq(StringUtils.isNotBlank(request.getSupplierId()), "supplier_id", request.getSupplierId())
                        .eq(StringUtils.isNotBlank(request.getBusinessTypeCode()), "business_type_code", request.getBusinessTypeCode())
                        .in("certificate_id", businessList.stream().map(o -> o.getCertificateId()).collect(Collectors.toList()))
        );

        return count;
    }
}
